﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Templay
{

    /// <summary>
    /// Style of parsed element
    /// </summary>
    public enum ParseElementType
    {
        ROOT,
        NORMAL,
        STYLE
    }

    /// <summary>
    /// An element of template
    /// </summary>
    public class ParseElement : ICloneable
    {
        /// <summary>
        /// Name of element
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Attributes of element
        /// </summary>
        public Dictionary<string, ParseAttribute> Attributes { get; set; }

        /// <summary>
        /// Child elements of element
        /// </summary>
        public List<ParseElement> Elements { get; set; }

        /// <summary>
        /// Type of element
        /// </summary>
        public virtual ParseElementType Type { get; set; }

        public ParseElement()
        {
            Elements = new List<ParseElement>();
            Attributes = new Dictionary<string, ParseAttribute>();
            Type = ParseElementType.NORMAL;
        }

        public ParseElement(string name)
        {
            Elements = new List<ParseElement>();
            Attributes = new Dictionary<string, ParseAttribute>();
            Name = name;

            if (name.ToLower() == "root")
                Type = ParseElementType.ROOT;
            else if (name.ToLower() == "style")
                Type = ParseElementType.STYLE;
            else
                Type = ParseElementType.NORMAL;
        }

        public string this[string attributeKey]
        {
            get
            {
                if (Attributes.ContainsKey(attributeKey))
                    return Attributes[attributeKey].Value;
                else
                    throw new Exception(String.Format("Attribute {0} doesn't exist !", attributeKey));
            }
        }

        /// <summary>
        /// Get if the parsed element have children elements
        /// </summary>
        public bool HasChildren
        {
            get
            {
                return Elements.Count() > 0;
            }
        }

        /// <summary>
        /// Get if the parsed element have
        /// </summary>
        /// <param name="attributeKey"></param>
        /// <returns></returns>
        public bool HasAttribute(string attributeKey)
        {
            return Attributes.ContainsKey(attributeKey);
        }

        /// <summary>
        /// Apply style to parsed element
        /// </summary>
        /// <param name="style">The style parsed element</param>
        public void ApplyStyle(ParseElement style)
        {
            if (style == null)
                return;

            foreach (var attribute in style.Attributes.Values)
            {
                if (Attributes.ContainsKey(attribute.Name))
                    Attributes[attribute.Name].Value = attribute.Value;
                else
                    Attributes.Add(attribute.Name, new ParseAttribute() { Name = attribute.Name, Value = attribute.Value });
            }
        }

        /// <summary>
        /// Clone the parsed element
        /// </summary>
        /// <returns>The parsed element clone</returns>
        public object Clone()
        {
            ParseElement parseElement = new ParseElement();

            foreach (var attribute in Attributes)
                parseElement.Attributes.Add(attribute.Key, attribute.Value);

            return parseElement;
        }

        public RootElement ToRootElement()
        {
            return new RootElement(this.Name, this["Assembly"], this["Namespace"]);
        }

    }
}
